/**
 * Project:   warnme-app
 * File:      LoginDialog.java
 * License: 
 *            This file is licensed under GNU General Public License version 3
 *            http://www.gnu.org/licenses/gpl-3.0.txt
 *
 * Copyright: Bartosz Cichecki [ cichecki.bartosz@gmail.com ]
 * Date:      Mar 29, 2014
 */

package dtu.ds.warnme.app.dialog;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.google.gson.reflect.TypeToken;

import dtu.ds.warnme.app.R;
import dtu.ds.warnme.app.application.Prefs;
import dtu.ds.warnme.app.dialog.listener.LoginDialogListener;
import dtu.ds.warnme.app.holders.UserProfileHolder;
import dtu.ds.warnme.app.model.impl.User;
import dtu.ds.warnme.app.utils.SecurityUtils;
import dtu.ds.warnme.app.utils.UiUtilities;
import dtu.ds.warnme.app.ws.client.https.GsonHttpResponseHandler;
import dtu.ds.warnme.app.ws.client.restful.RestClient;

/**
 * @author Bartosz Cichecki
 * 
 */
public class LoginDialog extends DialogFragment {

	private final static String TAG = "LoginDialog";

	private LoginDialogListener listener;

	private EditText usernameEditText;

	private EditText passwordEditText;

	private AlertDialog dialog;

	private View progressView;

	private View formView;

	private RestClient tempRestClient;

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
		try {
			listener = (LoginDialogListener) activity;
		} catch (ClassCastException ex) {
			throw new ClassCastException(activity.toString() + " must implement LoginDialogListener");
		}
	}

	@Override
	public Dialog onCreateDialog(Bundle savedInstanceState) {
		AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
		View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_login, null);
		builder.setView(view);
		builder.setTitle(R.string.login);
		builder.setPositiveButton(R.string.login, new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialogInterface, int which) {
				// Nothing do to here...
			}
		});

		builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialogInterface, int which) {
				// Nothing do to here...
			}
		});

		progressView = view.findViewById(R.id.dialog_login_progress);
		formView = view.findViewById(R.id.dialog_login_form);

		usernameEditText = (EditText) view.findViewById(R.id.dialog_login_edit_text_username);
		usernameEditText.addTextChangedListener(new TextWatcher() {

			@Override
			public void afterTextChanged(Editable s) {
				// Nothing to do here...
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after) {
				// Nothing to do here...
			}

			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
				usernameEditText.setError(null);
			}
		});

		passwordEditText = (EditText) view.findViewById(R.id.dialog_login_edit_text_password);
		passwordEditText.addTextChangedListener(new TextWatcher() {

			@Override
			public void afterTextChanged(Editable s) {
				// Nothing to do here...
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after) {
				// Nothing to do here...
			}

			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
				passwordEditText.setError(null);
			}
		});

		dialog = builder.create();

		dialog.setOnShowListener(new DialogInterface.OnShowListener() {

			@Override
			public void onShow(DialogInterface dialogInterface) {

				final Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
				positiveButton.setOnClickListener(new View.OnClickListener() {

					@Override
					public void onClick(View v) {
						final String username = usernameEditText.getText().toString();
						String password = passwordEditText.getText().toString();

						boolean formOk = true;

						if (StringUtils.isBlank(username)) {
							usernameEditText.setError(getString(R.string.cannot_be_empty));
							formOk = false;
						}
						if (StringUtils.isBlank(password)) {
							passwordEditText.setError(getString(R.string.cannot_be_empty));
							formOk = false;
						}

						if (!formOk) {
							Log.d(TAG, "Form contains errors.");
							return;
						}

						final String hashedPassword = SecurityUtils.hashSHA512Base64(password);

						tempRestClient = new RestClient(Prefs.getHost(), Prefs.getPort(), Prefs.getWsContextPath(), username,
						        hashedPassword, Prefs.getRealm());
						tempRestClient.getProfile(dialog.getContext(), new GsonHttpResponseHandler<User>(new TypeToken<User>() {
						}.getType()) {

							@Override
							public void onFailure(int statusCode, Header[] headers, String responseBody, Throwable error) {
								Log.e(TAG, "Login failed. [statusCode = " + statusCode + ", error=" + error + "]");

								if (statusCode == 0) {
									Toast.makeText(dialog.getOwnerActivity(), R.string.check_connection, Toast.LENGTH_LONG).show();
									return;
								}

								usernameEditText.setError(getResources().getText(R.string.bad_username_or_password));
								passwordEditText.setError(getResources().getText(R.string.bad_username_or_password));
								listener.onLoginFailure();
							}

							@Override
							public void onFinish() {
								positiveButton.setEnabled(true);
								UiUtilities.fadeInFadeOut(formView, progressView);
							}

							@Override
							public void onStart() {
								positiveButton.setEnabled(false);
								UiUtilities.fadeInFadeOut(progressView, formView);
							}

							@Override
							public void onSuccess(int statusCode, Header[] headers, User user) {
								Log.i(TAG, "Login succeeded. [statusCode = " + statusCode + "]");
								UserProfileHolder.setUserProfile(user);
								Prefs.setUsername(username);
								Prefs.setPasswordHash(hashedPassword);
								dialog.dismiss();

								listener.onLoginSuccess();
							}

						});

					}
				});

				final Button negativeButton = dialog.getButton(DialogInterface.BUTTON_NEGATIVE);
				negativeButton.setOnClickListener(new View.OnClickListener() {

					@Override
					public void onClick(View v) {
						if (tempRestClient != null) {
							tempRestClient.cancelRequests(dialog.getOwnerActivity(), true);
						}
						dialog.dismiss();
					}
				});
			}
		});

		return dialog;
	}

	@Override
	public void onDismiss(DialogInterface dialogInterface) {
		super.onDismiss(dialog);

		if (tempRestClient != null) {
			tempRestClient.cancelRequests(dialog.getContext(), true);
		}
	}

}
